#include "pj_worker.hpp"

/**************************************  STATIC VARIALBES *******************************/
static bool hasTask = false;

/************************************** SHARED VARIABLES ********************************/
static sem_t* sharedSem;
static struct_val_manager_worker* sharedMMap;

/*
 * signal handler of manager process, (special function)
 * para: int signo: ID of signal; use some static gbl vals inside
 * return: none
 *
 * note: may exit inside
 * note: has send() inside, and there is send()'s only location
 */
void workerSignal_handler(int signo){
	if (signo == SIGUSR2){
		hasTask = true;
	}
	else{
		cout << "worker " << getpid() << " unknown signo:" << signo << endl;
	}
}

/*
 * init worker
 */
void workerInit(){
	struct sigaction newsignal;
	newsignal.sa_flags = 0;   //this is a FUCK THING that musts be clear, C don't initialized memory with 0 automatically!
	newsignal.sa_handler = workerSignal_handler;
	
	//set signal handlers
	if (sigemptyset(&newsignal.sa_mask) == -1){
		cerr << "sigemptyset" << endl;
		abort();
	}

	if (sigaddset(&newsignal.sa_mask, SIGUSR2)){
		cerr << "sigaddset SIGUSR2" << endl;
		abort();
	}
	
	if (sigaction(SIGUSR2, &newsignal, NULL) == -1)
	{
		cerr << "sigaction SIGUSR2" << endl;
		abort();
	}
	
	sem_wait(sharedSem);
}


/*
 * process of producer, head function, with exit() inside, should with recv/send/close in inside function 
 * exit(0): add good OK, exit(other): error
 */
void WorkerInterface(sem_t* ss, struct_val_manager_worker* sm){
	sharedSem = ss;
	sharedMMap = sm;
	workerInit();
	cout << "worker " << getpid() << " init ok" << endl;
	
	while(true){
		//block, wait for hasTask, hasTask is set by signal: SIGUSR2, by manager process!
		//should use sleep and awake in next version
		usleep(100000);
		if(hasTask){
			//get task
			string recvRawStr = (string)sharedMMap->content;
			cout << "LOG::worker: "<< getpid() << " get a task, length:" << recvRawStr.size() << endl;
			
			//exec task
			string sendStr = taskExec(recvRawStr);
			
			//return result
			memset(sharedMMap->content, 0, MMAP_CONTENT_LENGTH - 1);
			const char* tempSendStrC = sendStr.c_str();
			memcpy(sharedMMap->content, tempSendStrC, sendStr.size() + 1);
			cout << "worker: " << getpid() << " task finished :)" << endl;
			hasTask = false;
			
			sem_post(sharedSem);
			
			if (kill(getppid(), SIGUSR2) == -1){
				cout << "worker: " << getpid() << " send siguser2 to manager: " << getppid() << "error" << endl;
			}
			else{
				cout << "worker: " << getpid() << " send siguser2 to manager: " << getppid() << "success" << endl;
			}
		}
		else{
			continue;
		}
	}
}
